﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace SFP.Animation2D
{
    public class PSPreset
    {
        // Emitter Prefs
        public bool linearEmittInterpolation = false;
        public double amountPerSec = 100;
        public double velocity = 50;
        public double velocityRan = 0;
        public double direction = 0;
        public double directionRan = 100;

        // Particle Prefs
        public int particleType = ParticleSystem.PARTICLE_CIRCLE;
        public string particleImgPath = "";
        public double liveTime = 1;
        public double liveTimeRan = 0;
        public double size = 1;
        public double sizeRan = 0;
        public double rotation = 0;
        public double rotationRan = 0;
        public double rotationSpeed = 0;
        public double rotationSpeedRan = 0;
        public double opacity = 100;
        public double opacityRan = 0;
        public Color color = Color.White;

        // Physics Prefs
        public double gravity = 0;

        public XDocument exportXML()
        {
            XDocument document = new XDocument();

            XElement root = new XElement("PSPreset");

            // Export Emitter Prefs...
            XElement emitterElem = new XElement("Emitter");
            addElementForParam("LinearEmittInterpolation", linearEmittInterpolation, emitterElem);
            addElementForParam("AmountPerSec", GetStringFromDouble(amountPerSec), emitterElem);
            addElementForParam("Velocity", GetStringFromDouble(velocity), emitterElem);
            addElementForParam("VelocityRan", GetStringFromDouble(velocityRan), emitterElem);
            addElementForParam("Direction", GetStringFromDouble(direction), emitterElem);
            addElementForParam("DirectionRan", GetStringFromDouble(directionRan), emitterElem);
            root.Add(emitterElem);

            // Export Particle Prefs...
            XElement particleElem = new XElement("Particle");
            addElementForParam("ParticleType", particleType, particleElem);
            addElementForParam("ParticleImgPath", particleImgPath, particleElem);
            addElementForParam("LiveTime", GetStringFromDouble(liveTime), particleElem);
            addElementForParam("LiveTimeRan", GetStringFromDouble(liveTimeRan), particleElem);
            addElementForParam("Size", GetStringFromDouble(size), particleElem);
            addElementForParam("SizeRan", GetStringFromDouble(sizeRan), particleElem);
            addElementForParam("Rotation", GetStringFromDouble(rotation), particleElem);
            addElementForParam("RotationRan", GetStringFromDouble(rotationRan), particleElem);
            addElementForParam("RotationSpeed", GetStringFromDouble(rotationSpeed), particleElem);
            addElementForParam("RotationSpeedRan", GetStringFromDouble(rotationSpeedRan), particleElem);
            addElementForParam("Opacity", GetStringFromDouble(opacity), particleElem);
            addElementForParam("OpacityRan", GetStringFromDouble(opacityRan), particleElem);
            addElementForParam("Color", color.R + "," + color.G + "," + color.B, particleElem);
            root.Add(particleElem);

            // Export Physics Prefs...
            XElement physicsElem = new XElement("Physics");
            addElementForParam("Gravity", GetStringFromDouble(gravity), physicsElem);
            root.Add(physicsElem);

            document.Add(root);

            return document;
        }

        private void addElementForParam(string name, object value, XElement parentElem)
        {
            XElement paramElem = new XElement(name);
            paramElem.SetValue(value);
            parentElem.Add(paramElem);
        }

        private string GetStringFromDouble(double value)
        {
            return ("" + value).Replace('.', ',');
        }

        public void importXML(XDocument document)
        {
            if (document == null) return;

            foreach (XNode node in document.Root.Nodes())
            {
                if (node is XElement)
                {
                    XElement element = (XElement)node;

                    // Import Emitter Prefs...
                    if ("Emitter".Equals(element.Name.LocalName))
                    {
                        foreach (XNode emitterNode in element.Nodes())
                        {
                            if (emitterNode is XElement)
                            {
                                XElement emitterElement = (XElement)emitterNode;

                                if ("LinearEmittInterpolation".Equals(emitterElement.Name.LocalName))
                                    linearEmittInterpolation = GetBoolFromString(emitterElement.Value);
                                else if ("AmountPerSec".Equals(emitterElement.Name.LocalName))
                                    amountPerSec = GetDoubleFromString(emitterElement.Value, 0);
                                else if ("Velocity".Equals(emitterElement.Name.LocalName))
                                    velocity = GetDoubleFromString(emitterElement.Value, 0);
                                else if ("VelocityRan".Equals(emitterElement.Name.LocalName))
                                    velocityRan = GetDoubleFromString(emitterElement.Value, 0);
                                else if ("Direction".Equals(emitterElement.Name.LocalName))
                                    direction = GetDoubleFromString(emitterElement.Value, 0);
                                else if ("DirectionRan".Equals(emitterElement.Name.LocalName))
                                    directionRan = GetDoubleFromString(emitterElement.Value, 0);
                            }
                        }
                    }

                    // Import Particle Prefs...
                    if ("Particle".Equals(element.Name.LocalName))
                    {
                        foreach (XNode particleNode in element.Nodes())
                        {
                            if (particleNode is XElement)
                            {
                                XElement particleElement = (XElement)particleNode;

                                if ("ParticleType".Equals(particleElement.Name.LocalName))
                                    particleType = GetIntFromString(particleElement.Value, 0);
                                else if ("ParticleImgPath".Equals(particleElement.Name.LocalName))
                                    particleImgPath = particleElement.Value;
                                else if ("LiveTime".Equals(particleElement.Name.LocalName))
                                    liveTime = GetDoubleFromString(particleElement.Value, 0);
                                else if ("LiveTimeRan".Equals(particleElement.Name.LocalName))
                                    liveTimeRan = GetDoubleFromString(particleElement.Value, 0);
                                else if ("Size".Equals(particleElement.Name.LocalName))
                                    size = GetDoubleFromString(particleElement.Value, 0);
                                else if ("SizeRan".Equals(particleElement.Name.LocalName))
                                    sizeRan = GetDoubleFromString(particleElement.Value, 0);
                                else if ("Rotation".Equals(particleElement.Name.LocalName))
                                    rotation = GetDoubleFromString(particleElement.Value, 0);
                                else if ("RotationRan".Equals(particleElement.Name.LocalName))
                                    rotationRan = GetDoubleFromString(particleElement.Value, 0);
                                else if ("RotationSpeed".Equals(particleElement.Name.LocalName))
                                    rotationSpeed = GetDoubleFromString(particleElement.Value, 0);
                                else if ("RotationSpeedRan".Equals(particleElement.Name.LocalName))
                                    rotationSpeedRan = GetDoubleFromString(particleElement.Value, 0);
                                else if ("Opacity".Equals(particleElement.Name.LocalName))
                                    opacity = GetDoubleFromString(particleElement.Value, 0);
                                else if ("OpacityRan".Equals(particleElement.Name.LocalName))
                                    opacityRan = GetDoubleFromString(particleElement.Value, 0);
                                else if ("Color".Equals(particleElement.Name.LocalName))
                                {
                                    string[] channelValues = particleElement.Value.Split(',');
                                    int r = GetIntFromString(channelValues[0], 0);
                                    int g = GetIntFromString(channelValues[1], 0);
                                    int b = GetIntFromString(channelValues[2], 0);
                                    
                                    color = Color.FromArgb(r, g, b);
                                }
                            }
                        }
                    }

                    // Import Physics Prefs...
                    if ("Physics".Equals(element.Name.LocalName))
                    {
                        foreach (XNode physicsNode in element.Nodes())
                        {
                            if (physicsNode is XElement)
                            {
                                XElement physicsElement = (XElement)physicsNode;

                                if ("Gravity".Equals(physicsElement.Name.LocalName))
                                    gravity = GetDoubleFromString(physicsElement.Value, 0);
                            }
                        }
                    }
                }
            }
        }

        private int GetIntFromString(string value, int defaultValue)
        {
            try
            {
                return int.Parse(value);
            }
            catch (FormatException)
            {
                return defaultValue;
            }
        }

        private double GetDoubleFromString(string value, double defaultValue)
        {
            try
            {
                return double.Parse(value);
            }
            catch (FormatException)
            {
                return defaultValue;
            }
        }

        private bool GetBoolFromString(string value)
        {
            try
            {
                return bool.Parse(value);
            }
            catch (FormatException)
            {
                return false;
            }
        }

        public override string ToString()
        {
            return "Emitter:\n" +
                   "AmountPerSec=" + amountPerSec + "\n" +
                   "Velocity=" + velocity + "\n" +
                   "VelocityRan=" + velocityRan + "\n" +
                   "Direction=" + direction + "\n" +
                   "DirectionRan=" + directionRan + "\n" +
                   "Particle:\n" +
                   "ParticleType=" + particleType + "\n" +
                   "ParticleImgPath=" + particleImgPath + "\n" +
                   "LiveTime=" + liveTime + "\n" +
                   "LiveTimeRan=" + liveTimeRan + "\n" +
                   "Size=" + size + "\n" +
                   "SizeRan=" + sizeRan + "\n" +
                   "Rotation=" + rotation + "\n" +
                   "RotationRan=" + rotationRan + "\n" +
                   "RotationSpeed=" + rotationSpeed + "\n" +
                   "Opacity=" + opacity + "\n" +
                   "OpacityRan=" + opacityRan + "\n" +
                   "Color=" + color.R + "," + color.G + "," + color.B +
                   "Physics:\n" +
                   "Gravity=" + gravity + "\n";
        }
    }
}
